package com.github.tommas.admintpl.security;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;

public class LoginAuthenticationFilter extends FormAuthenticationFilter {
    public static final String AUTHENTICATION_EXCEPTION_CLASS_ATTR = "authentication_exception_class";

    private static final Logger LOGGER = LoggerFactory.getLogger(LoginAuthenticationFilter.class);

    @Override
    protected AuthenticationToken createToken(String username, String password, boolean rememberMe, String host) {
        return new AuthenticationToken(username, password, rememberMe, host);
    }

    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
        return !isLoginRequest(request, response) && super.isAccessAllowed(request, response, mappedValue);
    }

    @Override
    protected boolean onLoginSuccess(org.apache.shiro.authc.AuthenticationToken token, Subject subject, ServletRequest request, ServletResponse response) throws Exception {
        return true;
    }

    @Override
    protected boolean onLoginFailure(org.apache.shiro.authc.AuthenticationToken token, AuthenticationException e, ServletRequest request, ServletResponse response) {
        if (LOGGER.isDebugEnabled()) {
            LOGGER.debug("Authentication exception", e);
        }

        Subject subject = SecurityUtils.getSubject();
        if (subject != null && subject.isAuthenticated()) {
            subject.logout();
        }

        HttpServletResponse resp = (HttpServletResponse) response;
        resp.setStatus(HttpServletResponse.SC_UNAUTHORIZED);

        request.setAttribute(AUTHENTICATION_EXCEPTION_CLASS_ATTR, e.getClass());

        return super.onLoginFailure(token, e, request, response);
    }
}
